package mapEditor.obj;

import debug.*;

import mapEditor.map.ObjectModel;
import mapEditor.utils.MapLocation;
import mapEditor.utils.FontStyle;
import mapEditor.utils.StrokeStyle;
import mapEditor.utils.Util;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Dimension;
//import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Toolkit;
//import java.awt.font.LineMetrics;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.geom.AffineTransform;
import java.awt.image.ImageObserver;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPanel;


public class TextObject extends DrawObject
{ private static final String TAG="mapEditor.obj.DrawObject";
//  private static final boolean VERBOSE=true;
  private static final boolean DEBUG=false;//true;

  public static final String TYPE="Text";
	
  private double ANGLE=0;	
  private String TEXT="";
  public String getText() { return(TEXT); }
  protected void setText(String newValue)
  { if(!TEXT.equals(newValue))
    { String oldValue=TEXT; TEXT=newValue;
      justifySecondPoint();
      FIRE_CHANGE_EVENT("TEXT["+oldValue+"==>"+newValue+"]");
    }
  }
  
  public TextObject(ObjectModel objectModel,MapLocation p1) throws JSONException
  { super(objectModel,null);
    stroke.setEnabled(true);
	add(p1); add(p1.copy());
	justifySecondPoint();
  }
  
  public TextObject(ObjectModel objectModel,JSONObject jsonObject) throws JSONException
  { super(objectModel,jsonObject.getString("id"));
	if(DEBUG) Log.d(TAG,"<init>: jsonObject="+jsonObject);
    this.font=new FontStyle(jsonObject);
    this.stroke=new StrokeStyle(jsonObject);
    clearPointSet();
    JSONArray p1=jsonObject.getJSONArray("p1");
    add(MapLocation.newPixelPoint(objectModel,p1));
    TEXT=jsonObject.optString("#text","");
    ANGLE=jsonObject.optDouble("rotate",0);
	add(getMapLocation(0).copy());
    justifySecondPoint();
  }

  public JSONObject toJSONObject() throws JSONException
  { JSONObject jsonObject=new JSONObject();
    jsonObject.put("type",TYPE);
    jsonObject.put("id",getIdent());
    MapLocation p1=getMapLocation(0);
//	MapLocation p2=getMapLocation(1);
    jsonObject.put("id",getIdent());
    jsonObject.put("p1",p1.encode());
    jsonObject.put("#text",getText());
    if(ANGLE!=0) jsonObject.put("rotate",ANGLE); else jsonObject.remove("rotate");
    jsonObject.put("font",font.encode());
    jsonObject.put("stroke",stroke.encode());
	return(jsonObject);
  }
  
  private int getStringWidth(String s)
  { FontMetrics fontMetrics=Toolkit.getDefaultToolkit().getFontMetrics(font.getFont(objectModel.getCurrentZoom())); 
	int width=fontMetrics.stringWidth(s);
	return(width);
  }
  
  private double getStringWidth(Graphics2D g,String s)
  { FontRenderContext frc=g.getFontRenderContext();
	Rectangle2D rect=font.getFont(objectModel.getCurrentZoom()).getStringBounds(TEXT,frc); 
	double width=rect.getWidth();
	if(DEBUG) Log.d(TAG,"getStringWidth: "+s+", width="+width+", OLD width="+getStringWidth(s));
	return(width);
  }
  
  
  private void justifySecondPoint()
  {	MapLocation p0=getMapLocation(0);
	MapLocation p1=getMapLocation(1);
    int w=getStringWidth(getText());
    double dy=w*Math.sin(ANGLE);
    double dx=w*Math.cos(ANGLE);
    if(DEBUG) Log.d(TAG,"justifySecondPoint: w="+w+", dx="+dx+", dy="+dy+", rad="+ANGLE+", deg="+Math.toDegrees(ANGLE));
    p1.setX(p0.getX()+dx); // TODO: TEST	
    p1.setY(p0.getY()+dy); // TODO: TEST	
  }
  
  private void calculateAngle()
  {	MapLocation p0=getMapLocation(0);
 	MapLocation p1=getMapLocation(1);
    double x0=(float)p0.getX();
    double y0=(float)p0.getY();
    double x1=(float)p1.getX();
    double y1=(float)p1.getY();
    // Calculate angle
    double dx=x1-x0;
    double dy=y1-y0;
    ANGLE=Math.atan2(dy,dx);
    if(DEBUG) Log.d(TAG,"calculateAngle: dx="+dx+", dy="+dy+", rad="+ANGLE+", deg="+Math.toDegrees(ANGLE));
  }
  
  public void paint(Graphics2D g,ImageObserver imageObserver)
  {	MapLocation p0=getMapLocation(0);
    calculateAngle();
    justifySecondPoint();
    //Get the current transform
    AffineTransform originalTransform=g.getTransform();
    // Perform transformation
    AffineTransform trans=(AffineTransform)originalTransform.clone();
    trans.rotate(ANGLE,(float)p0.getX(),(float)p0.getY());
    g.setTransform(trans);
    // Render
    Util.drawString(g,getText(),(float)p0.getX(),(float)p0.getY(),objectModel.getCurrentZoom(),font,stroke);
    // Restore original transform
    g.setTransform(originalTransform); // Restore original transform
  }
  
  
  // ****************************************************************
  // *** INNER CLASS: EditGeneralPanel
  // ****************************************************************
  public JPanel getEditGeneralPanel(String title)
  { return(new EditGeneralPanel(title)); }
  private class EditGeneralPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC
    private JTextField identField;
    private JTextField textField;
    private JButton strokeButton;
    
    public void paint(Graphics g)
    { if(DEBUG) Log.d(TAG,"EditGeneralPanel.paint: ");
      identField.setText(getIdent());
      strokeButton.setBackground(stroke.getColor());
  	  super.paint(g);  
    }
  	
    public EditGeneralPanel(String title)
    { setBorder(Util.getTitleBorder(title));
      setPreferredSize(new Dimension(350,120));
      setLayout(new GridLayout(5,2));
      add(new JLabel("Ident:"));
      identField=new JTextField(getIdent());
      identField.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { setIdent(identField.getText()); }
      });
      add(identField);
      add(new JLabel("Text:"));
      textField=new JTextField(getText());
      textField.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { setText(textField.getText()); }
      });
      add(textField);
   	  addEditFontButton(this);
      strokeButton=addEditStrokeButton(this,false);
    }
  }    

}
